#include "BF_Defines.h"
#include "SCM_Lib.h"
#include "UT_DM_Defines.h"
#include "HF_Lib.h"

int find_operator(char* op);

int SCM_Insert(int argc, char * argv[])
{
	int i,j;
	relDesc reldesc;
	attrDesc * attrs;
	//elegxos ean iparxei to onoma tis sxesis
	if( (UTE_errno = CFM_Lookup(argv[1], &reldesc, &attrs) ) < 0 )
	{
		return UTE_errno;
	}

	//briskw ola ta attributes mesa sta orismata tis sinartisis argv
	for( i = 0; i < reldesc.attrcnt; i++ )
	{				//gia kathe attribute
		for(j = 2;j < argc; j+=2)
		{			//psakse ola ta orismata tis sinartisi
					//ean einai idia kane break
			if( !strcmp(attrs[i].attrname, argv[j] ) )
			{
				break;
			}
			//ean to j eiani > = argv simenei oti den brike kapoio attribute opote
			if( j >= argc)
			{
				return UTE_errno = SCM_INSERT;
			}
		}
	}
	
	//briksw ola ta orismata mesa sta attributes
	for(i = 0; i < argc; i +=2)
	{
		for(j = 0; j < reldesc.attrcnt; j++)
		{
			if(!strcmp(attrs[j].attrname, argv[i]) )
			{
				break;
			}
			
		}
		if( j >= reldesc.attrcnt )
		{
			return UTE_errno = SCM_INSERT;
		}
	}
	//me auto ton tropo eksasfalizw kai swsto arithmo orismatwn kai oti einai ola
	
	free(attrs);
	return UTE_OK;
}

int SCM_Select ( int argc, char *argv[] )
{
	BOOLEAN condition;
	char record[MAXNAME], relName[MAXNAME];
	int i, j, scanDesc, attrStart, attributesCount, counter = 0, retval;

	/* Ελεγχος για αν υπαρχουν τα attributes και η σχεση
	  ελεγχος αν εμφανιζονται μονο attributes μιας σχεσης
	  αν εχει σχεση αποτελεσματος, ελεγχος για να μην υπαρχει ηδη
	 */

	/* Αν έχουμε ονομα σχέσης αποτελέσματος. */

	if ( argc % 2 == 1 )
	{
		/*Ελέγχω αν το όνομα της σχέσης αποτελέσματος είναι όνομα
		 *ήδη υπάρχουσας σχέσης στη βάση.
		 */
		
		if ( ( scanDesc = HF_OpenFileScan ( relCatFd, sizeof(relDesc), 'c', MAXNAME, 0, EQUAL, argv[1] ) ) < 0 )
		{
			HF_PrintError("SCM Select error");
			return UTE_errno = UTE_HF_ERROR;
		}

		if ( HF_FindNextRec ( scanDesc, record ) != HFE_EOF )
		{
			return UTE_errno = UTE_EXISTS;
		}

	}

	/* Εύρεση απο πού ξεκινανε  τα attributes. */
	
	if ( argc % 2 == 1 )
	{
		attrStart = 4;
	}
	else
	{
		attrStart = 3;
	}

	attributesCount = atoi ( argv[ attrStart - 2] );

	/* Έλεγχος αν εμφανίζονται attributes μόνο μιας σχέσης. */

	strncpy ( relName, argv[attrStart - 1], MAXNAME );

	for ( i = attrStart + 2, j = 1; j < attributesCount; i += 2, j++ )
	{
		if ( strcmp ( argv[i], relName ) != 0 )
		{
			return UTE_errno = SCM_ONEREL;
		}
	}

	/* Έλεγχος αν όλα τα ονόματα πεδίων και σχέσεων είναι μέχρι MAXNAME. */

	for ( i = attrStart; i < argc; i++ )
	{
		if ( strlen ( argv[i] ) > MAXNAME )
		{
			return UTE_errno = SCM_MAXNAME;
		}
	}

	/* Έλεγχος αν υπάρχουν τα επιλεγμένα attributes στην σχέση. */

	if ( ( scanDesc = HF_OpenFileScan ( attrCatFd, sizeof(attrDesc), 'c', MAXNAME, 0 , EQUAL, relName ) ) < 0 )
	{
		HF_PrintError ( "Error in SCM_Select" );
		return UTE_errno = UTE_HF_ERROR;
	}

	while (  ( retval = HF_FindNextRec ( scanDesc, record ) ) != HFE_EOF )
	{
		if ( retval < 0 )
		{
			HF_PrintError ( "Error in scm select" );
			return UTE_errno = SCM_SELECT;
		}

		for ( i = attrStart, j = 0; j < attributesCount; i += 2, j++ )
		{
			if ( strcmp ( argv[i], record[MAXNAME + 1] == 0 ) )
			{
				counter++;
				break;
			}
		}
	}

	/* Αν όλα τα attributes δεν ανήκουν στην σχέση. */

	if ( counter != attributesCount )
	{
		return UTE_errno = SCM_SELECT;
	}

	/* Έλεγχος αν έχουμε συνθήκη πάνω σε κάποια απο τα προβαλόμενα attributes. */

	if ( argc % 2 == 0 && argc == 2 * attributesCount + 4 )
	{
		condition = FALSE;
	}
	else if ( argc % 2 == 1 && argc == 2 * attributesCount + 3 )
	{
		condition = FALSE;
	}
	else
	{
		condition = TRUE;
	}

	/* Αν δεν έχουμε συνθήκη τελειώνουν οι έλεγχοι. */

	if ( condition == FALSE )
	{
		return UTE_OK;
	}

	/* Άν έχουμε συνθήκη, ελέγχουμε αν το πεδίο επιλογής ανήκει στην σχέση που δίνεται
	 * και αν ο τελεστής είναι έγκυρος.
	 */

	if ( IsOperator ( argv[argc - 2] ) == FALSE )
	{
		return UTE_errno = SCM_SELECT;		
	}

	/* Έλεγχος αν η σχέση και το πεδίο είναι έγκυρα. */

	if ( strcmp ( argv[argc - 4], relName ) != 0 )
	{
		return UTE_errno = SCM_SELECT;		
	}

	/* Κοιτάω αν το attribute της συνθήκης υπάρχει στην σχέση. */

	if ( ( scanDesc = HF_OpenFileScan ( attrCatFd, sizeof(attrDesc), 'c', MAXNAME, MAXNAME, EQUAL, argv[argc - 3] ) ) < 0 )
	{
			HF_PrintError ( "Error in scm select" );
			return UTE_errno = SCM_SELECT;		
	}

	while (  ( retval = HF_FindNextRec ( scanDesc, record ) ) != HFE_EOF )
	{
		if ( retval < 0 )
		{
			HF_PrintError ( "Error in scm select" );
			return UTE_errno = SCM_SELECT;
		}

		if ( strncmp ( record, argv[argc - 4], MAXNAME ) == 0 )
		{
			/* Αν υπάρχει το attribute στη σχέση, επιστροφή επιτυχή ελέγχου. */
			return UTE_errno = UTE_OK;
		}
	}

	return SCM_SELECT;
}

BOOLEAN IsOperator ( char *op )
{
	if ( strcmp ( op, "=" ) == 0 )
	{
		return TRUE;
	}
	if ( strcmp ( op, "<" ) == 0 )
	{
		return TRUE;
	}
	if ( strcmp ( op, ">" ) == 0 )
	{
		return TRUE;
	}
	if ( strcmp ( op, "<=" ) == 0 )
	{
		return TRUE;
	}
	if ( strcmp ( op, ">=" ) == 0 )
	{
		return TRUE;
	}
	if ( strcmp ( op, "!=" ) == 0 )
	{
		return TRUE;
	}

	return FALSE;
}

int SCM_Delete(int argc, char* argv[])
{
	relDesc reldesc;
	attrDesc * attrs;
	int i;

	//elegxos gia swsto ari8mo orismatwn
	if (argc!=2 && argc!=5)
		return UTE_errno=SCM_DELETE;

	//elegxos ean iparxei to onoma tis sxesis
	if( (UTE_errno = CFM_Lookup(argv[1], &reldesc, &attrs) ) < 0 )
	{
		return UTE_errno;
	}

	if ( argc == 5)
	{
		//elegxos an yparxei to pedio poy mas dinei
		for( i = 0; i < reldesc.attrcnt; i++ )
		{
			if(!strcmp(attrs[i].attrname, argv[2]) )
			{
				break;
			}	

		}

		if( i >= reldesc.attrcnt )  // an to kseperasei de 8a exei brei to pedio
		{
			return UTE_errno = SCM_DELETE;
		}
		
		if ( (UTE_errno=find_operator(argv[3])) < 0)   // an dw8ei kati poy den einai operator
			return UTE_errno;
	}
}

int SCM_Join(int argc, char* argv[])
{
	int i, j, start;
	relDesc reldesc_a, reldesc_b;
	attrDesc * attrs_a, *attrs_b;

	if ( argc < 9 )      // prepei na yparxoyn toylaxiston 10 orismata (0-9) 
		return UTE_errno=SCM_JOIN;     ///////////////// ????  bale ayto sta defines

	// elegxos wste na mhn einai idies oi 2 sxeseis pros sygkrish
	if ( !strcmp(argv[argc-5], argv[argc-2]) )
		return UTE_errno=SCM_JOIN;

	//elegxos ean iparxoyn ta onomata twn sxesewn pros sygkrish kai ta pedia toys
	if( (UTE_errno = CFM_Lookup(argv[argc-5], &reldesc_a, &attrs_a) ) < 0 )
	{
		return UTE_errno;
	}

	for( i = 0; i < reldesc_a.attrcnt; i++ )
	{
		if(!strcmp(attrs_a[i].attrname, argv[argc-4]) )   // an yparxei to pedio poy mas dinei
		{						// gia th sxesh-zeyksh 1
			break;
		}	
	}

	if( i >= reldesc_a.attrcnt )
	{
		return UTE_errno = SCM_JOIN;
	}

	if( (UTE_errno = CFM_Lookup(argv[argc-2], &reldesc_b, &attrs_b) ) < 0 )
	{
		return UTE_errno;
	}

	for( i = 0; i < reldesc_b.attrcnt; i++ )
	{
		if(!strcmp(attrs_b[i].attrname, argv[argc-1]) )   // an yparxei to pedio poy mas dinei
		{						// gia th sxesh-zeyksh 2
			break;
		}	
	}

	if( i >= reldesc_b.attrcnt )
	{
		return UTE_errno = SCM_JOIN;
	}

	//elegxos an einai ok o telesths sygkrishs
	if ( (UTE_errno=find_operator(argv[argc-3])) < 0)   // an dw8ei kati poy den einai operator//// ?????? ayth einai h dikia moy...bale an 8es th dikia soy
			return UTE_errno;

	// an exoyme to proairetiko orisma "onoma sxeshs apotelesmatos"
	if ( argc % 2 == 0 )
	{
		// elegxoyme to onoma ayto na mhn einai idio me kapoia apo tis 2 sxeseis
		if ( !strcmp(argv[argc-5], argv[1]) || !strcmp(argv[argc-2], argv[1]) )
			return UTE_errno = SCM_JOIN;

		start=3;  //// oi probalomenes sxeseis arxizoyn apo th 8esh 3
	}
	else   // an den exoyme to proairetiko orisma
		start=2;  // oi probalomenes sxeseis arxizoyn apo th 8esh 2

	// elegxoyme an oi proballomenes sxeseis einai mia apo tis 2 sxeseis pros sygkrish
	for ( i=start; i<=argc-7; i+=2)
	{
		if ( !strcmp(argv[i], argv[argc-5]) )  // an h probalomenh sxesh einai h sxesh-zeyksh 1
		{

			for( j = 0; j < reldesc_a.attrcnt; j++ )
			{
				if(!strcmp(attrs_a[j].attrname, argv[i+1]) )   // an yparxei to pedio poy mas dinei
				{						// gia th proballomenh sxesh
					break;
				}	
			}

			if( j >= reldesc_a.attrcnt )
			{
				return UTE_errno = SCM_JOIN;
			}
		}

		else if ( !strcmp(argv[i], argv[argc-2]) )  // an h probalomenh sxesh einai h sxesh-zeyksh 2
		{

			for( j = 0; j < reldesc_b.attrcnt; j++ )
			{
				if(!strcmp(attrs_b[j].attrname, argv[i+1]) )   // an yparxei to pedio poy mas dinei
				{						// gia th proballomenh sxesh
					break;
				}	
			}

			if( j >= reldesc_b.attrcnt )
			{
				return UTE_errno = SCM_JOIN;
			}
		}
		else  // an den einai kamia apo tis 2
			return UTE_errno = SCM_JOIN;
	}

	free(attrs_a);
	free(attrs_b);
	return UTE_errno = UTE_OK;
}
